package com.tsugun.mediaplayer.view.widget;

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.LinearLayout;

import com.tsugun.mediaplayer.R;

/**
 * 自定义滑动容器控件
 * Created by shize on 2017/4/20.
 */

public class SlidingPanel extends LinearLayout implements GestureDetector.OnGestureListener {
    private static final int ANIMATION_DURATION = 300;   //  从底部到上面需要时间

    private View mHandle;
    private View mContent;
    private int mContentRangeTop;   //content在父布局的移动范围
    private int mContentRangeBottom;
    private int mDownY;     //ACTION_DOWN时y的坐标
    private boolean mExpanded = false;  //是否展开
    private GestureDetector mGestureDetector;   //检测手势辅助类

    private OnSlidingView mOnSlidingView; // 滑动监听事件

    private boolean isPlayAnimation; // 是否在播放动画

    public SlidingPanel(Context context) {
        this(context, null);
    }

    public SlidingPanel(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SlidingPanel(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);

        isPlayAnimation = false;
        mGestureDetector = new GestureDetector(context, this);
        setOrientation(LinearLayout.VERTICAL);
    }


    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        mHandle = findViewById(R.id.id_handler);
        mContent = findViewById(R.id.id_content);
        if (mHandle == null) {
            throw new IllegalArgumentException("The handle attribute is required and must refer "
                    + "to a valid child.");
        }
        if (mContent == null) {
            throw new IllegalArgumentException("The content attribute is required and must refer "
                    + "to a valid child.");
        }
        mHandle.setClickable(true);
        mHandle.setOnTouchListener(touchListener);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec);
        View handle = mHandle;
        measureChild(handle, widthMeasureSpec, heightMeasureSpec);
        measureChild(mContent, MeasureSpec.makeMeasureSpec(widthSpecSize, MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(heightSpecSize, MeasureSpec.EXACTLY));
        setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        //获取自身的宽高
        final int width = r - l;
        final int height = b - t;
        mContentRangeTop = 0;
        mContentRangeBottom = b - t;
        final View handle = mHandle;
        int childHeight = handle.getMeasuredHeight();
        int childWidth = handle.getMeasuredWidth();

        handle.layout(0, height - childHeight, childWidth, height);

        final View content = mContent;
        if (!mExpanded) {
            mContent.layout(0, mContentRangeBottom, content.getMeasuredWidth(), mContentRangeBottom + content.getMeasuredHeight());
        } else {
            mContent.layout(0, mContentRangeTop, content.getMeasuredWidth(), mContentRangeTop + content.getMeasuredHeight());
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        long drawingTime = getDrawingTime();
        final View handle = mHandle;
        drawChild(canvas, handle, drawingTime);
        final View content = mContent;
        drawChild(canvas, content, drawingTime);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (checkAnimation()) return true;
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mDownY = (int) event.getY();
                if (mExpanded) {
                    mOnSlidingView.onTouchDown();
                }
                break;
            case MotionEvent.ACTION_MOVE:
                int nowY = (int) event.getY();
                moveContent(nowY - mDownY);
                break;
            case MotionEvent.ACTION_UP:
                adjustContentView();
                mOnSlidingView.onTouchUp();
                break;
        }
        return mExpanded;
    }

    /**
     * @return 是否正在播放动画
     */
    private boolean checkAnimation() {
        return isPlayAnimation;
    }

    /**
     * 停止滑动
     */
    private void stopTracking() {
        //判断content是展开还是收缩
        updateExpanded();
    }

    /**
     * 更新mExpanded状态
     */
    private void updateExpanded() {
        mExpanded = mContent.getTop() <= mContentRangeTop;
    }

    /**
     * @param position 指定位置
     */
    private void moveContent(int position) {
        //不能移出上边界
        if (position < mContentRangeTop) {
            position = mContentRangeTop;
        } else if (position > mContentRangeBottom) {
            position = mContentRangeBottom;
        }
        final View content = mContent;
        final int top = (int) mContent.getY();
        final int deltaY = position - top;
        content.layout(0, position, content.getWidth(), position + content.getHeight());
    }

    //移动Content
    private void doAnimation(final int nowY, final int targetY) {
        //BounceInterpolator bounceInterpolator=new BounceInterpolator();
        TranslateAnimation animation = new TranslateAnimation(0, 0, 0, targetY - nowY);
        animation.setDuration(ANIMATION_DURATION * Math.abs(targetY - nowY) / mContentRangeBottom);
        animation.setInterpolator(new AccelerateDecelerateInterpolator());
        animation.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) {
                // 防止点击造成判断动画还未停止的情况
                if (Math.abs(targetY - nowY) < 10){
                    isPlayAnimation = false;
                    mOnSlidingView.onFinishAnimation();
                    return;
                }
                isPlayAnimation = true;
                mOnSlidingView.onStartAnimation();
            }

            @Override
            public void onAnimationEnd(Animation animation) {
                //Log.i(TAG,"onAnimationEnd");
                isPlayAnimation = false;
                mContent.clearAnimation();
                mContent.layout(0, targetY, mContent.getMeasuredWidth(), targetY + mContent.getMeasuredHeight());
                stopTracking();
                mOnSlidingView.onFinishAnimation();
            }

            @Override
            public void onAnimationRepeat(Animation animation) {
            }
        });
        mContent.startAnimation(animation);
    }

    /**
     * 点击时打开Content*
     */
    private void open() {
        doAnimation(mContentRangeBottom, 0);
        stopTracking();
    }

    /**
     * ACTION_UP时 contentView不是停靠在屏幕边缘（在屏幕中间）时，调整contentView的位置*
     */
    private void adjustContentView() {
        final int top = mContent.getTop();
        //切割父容器，分成3等份
        final int perRange = (mContentRangeBottom - mContentRangeTop) / 6;
        if (mExpanded) {
            //小于1/3
            if (top < perRange + mContentRangeTop) {
                doAnimation(top, 0);
            } else {
                doAnimation(top, mContentRangeBottom);
            }
        } else {
            //小于2/3
            if (top < mContentRangeTop + perRange * 5) {
                doAnimation(top, 0);
            } else {
                doAnimation(top, mContentRangeBottom);
            }
        }

    }

    /**
     * 按下时触发
     */
    @Override
    public boolean onDown(MotionEvent e) {
        return false;
    }

    @Override
    public void onShowPress(MotionEvent e) {
    }

    /**
     * 轻轻点击
     */
    @Override
    public boolean onSingleTapUp(MotionEvent e) {
        if (!mExpanded) {
            open();
        }
        return false;
    }

    /**
     * 滚动时出发*
     */
    @Override
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {


        int touchY = (int) e2.getY();
        moveContent(touchY - mDownY + (mExpanded ? mContentRangeTop : mContentRangeBottom));
        return false;
    }

    /**
     * 长按
     */
    @Override
    public void onLongPress(MotionEvent e) {
    }

    /**
     * 瞬时滑动
     */
    @Override
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
        return false;
    }

    OnTouchListener touchListener = new OnTouchListener() {
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            if (checkAnimation()) return true;
            final View handle = mHandle;
            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                final int top = handle.getTop();
                mDownY = (int) event.getY();
                mOnSlidingView.onTouchDown();
            } else if (event.getAction() == MotionEvent.ACTION_UP) {
                adjustContentView();
                mOnSlidingView.onTouchUp();
            }
            return mGestureDetector.onTouchEvent(event);
        }
    };

    /**
     * @return 获取展开状态
     */
    public boolean getState() {
        return mExpanded;
    }

    /**
     * 关闭展开界面
     */
    public void close() {
        doAnimation(mContentRangeTop, mContentRangeBottom);
        stopTracking();
    }

    /**
     * 设置滑动事件监听器
     */
    public void setOnSlidingView(OnSlidingView onSlidingView) {
        mOnSlidingView = onSlidingView;
    }

    /**
     * 活动操作回调接口
     */
    public interface OnSlidingView {
        /**
         * 按下
         */
        void onTouchDown();

        /**
         * 松手
         */
        void onTouchUp();

        /**
         * 开始展开动画
         */
        void onStartAnimation();

        /**
         * 结束展开动画
         */
        void onFinishAnimation();
    }
}
